package com.navinfo.tripanalysis.common.arithmetic;

import com.navinfo.tripanalysis.common.arithmetic.annotation.Arithmetic;
import com.navinfo.tripanalysis.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.tripanalysis.common.util.ArithmeticUtils;
import com.navinfo.tripanalysis.common.arithmetic.common.CommonData;
import com.navinfo.tripanalysis.common.arithmetic.common.OuterStatisticData;
import com.navinfo.tripanalysis.common.arithmetic.custom.VarSharpAcceleration;
import com.navinfo.tripanalysis.common.arithmetic.enums.EventStatus;
import com.navinfo.tripanalysis.common.arithmetic.exception.RangeAssert;
import com.navinfo.tripanalysis.common.config.ConfigMap;
import com.navinfo.tripanalysis.common.arithmetic.enums.EventType;

import java.util.Optional;

/**
 * 东风急加速算法<br/>
 * 依赖{@link Mileage}里程油耗算法<br/>
 * 输出：统计、事件<br/>
 * @author web
 */
@Arithmetic(name = "东风急加速算法")
public class SharpAcceleration_DF extends AbstractArithmetic<VarSharpAcceleration> {
    /**
     * 算法名称
     */
    private final String arithmeticName = "东风急加速";
    /**
     * 事件类型
     */
    private final EventType EVENT_TYPE = EventType.sharpAcceleration_DF;

    /**
     * 加速度阀值,默认1.2m/s2
     */
    private final double accelerationThreshold = ConfigMap.getDouble("DF_Acc_Threshold");

    @Override
    public void calculate() {
        logger.debug("{}算法开始...", arithmeticName);
        VarSharpAcceleration var = super.getObj();
        CommonData commonData = drivingData.getCommonData();

        //1.油门开合度有效性验证
        RangeAssert.acceleratorIsInTheRange(commonData.getAcceleratorPosition());

        //是否急加速：加速度大于阀值 并且 油门开度>0
        boolean preIsSharpUpSpeed = var.isPreSharpUpSpeed();
        boolean curIsSharpUpSpeed = commonData.getAcceleration()>= accelerationThreshold && commonData.getAcceleratorPosition()>0;
        logger.debug("{}算法，急加速状态：pre:{},current:{}.", arithmeticName, preIsSharpUpSpeed, curIsSharpUpSpeed);

        //上一次或本次激烈加速，进入算法
        if (preIsSharpUpSpeed || curIsSharpUpSpeed) {
            EventStatus eventStatus = getEventStatus(preIsSharpUpSpeed, curIsSharpUpSpeed);
            switch (eventStatus) {
                case START:
                    logger.debug("{}算法，事件开始....", arithmeticName);
                    startEventData(EVENT_TYPE);
                    break;
                case IN:
                    logger.debug("{}算法，事件中...", arithmeticName);
                    calcEventData(EVENT_TYPE);
                    break;
                case END:
                    logger.debug("{}算法，事件结束...", arithmeticName);
                    calcEventData(EVENT_TYPE);
                    endEventData(var);
                    break;
                default:
            }
        }

        //行程结束时要清理对应的未结束事件
        if (getCommonData().isTripLastNode()) {
            endEventData(var);
        }

        //设置上一个点状态、供下个点计算
        var.setPreSharpUpSpeed(curIsSharpUpSpeed);
        logger.debug("{}算法结束...", arithmeticName);
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
        VarSharpAcceleration varSharpAcceleration = super.getObj();
        statisticDataOut.setSharpUpSpeedMileage_DF(ArithmeticUtils.mileageMToM(varSharpAcceleration.getMileage()));
        statisticDataOut.setSharpUpSpeedFuel_DF(ArithmeticUtils.fuelMlToMl(varSharpAcceleration.getFuel()));
        statisticDataOut.setSharpUpSpeedDuration_DF(ArithmeticUtils.timeMsToSecond(varSharpAcceleration.getDuration()));
        statisticDataOut.setSharpUpSpeedNumber_DF(varSharpAcceleration.getNumber());
    }

    private void endEventData(VarSharpAcceleration var){
        endEventData(EVENT_TYPE, eventData -> {
            var.setNumber(var.getNumber() + 1);
            var.addMileage( Optional.ofNullable(eventData.getExtendField05()).orElse(0.0));
            var.addFuel( Optional.ofNullable(eventData.getExtendField06()).orElse(0.0).intValue());
            var.addDuration( Optional.ofNullable(eventData.getDuration()).orElse(0L).intValue());
        });
    }
}
